package by.epam.trenings.vkphotorest.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class HttpManager {

	private static HttpManager instance;

	private DefaultHttpClient client;

	public static final int TIMEOUT = 20000;

	private static final String encoding = "UTF-8";

	private HttpManager() {
		HttpParams parameter = new BasicHttpParams();
		HttpProtocolParams.setVersion(parameter, HttpVersion.HTTP_1_1);
		HttpProtocolParams.setContentCharset(parameter, encoding);
		parameter.setBooleanParameter("http.protocol.expect-continue", false);
		HttpConnectionParams.setConnectionTimeout(parameter, TIMEOUT);
		HttpConnectionParams.setSoTimeout(parameter, TIMEOUT);

		SchemeRegistry registry = new SchemeRegistry();
		registry.register(new Scheme("http", PlainSocketFactory
				.getSocketFactory(), 80));
		final SSLSocketFactory sslSocketFactory = SSLSocketFactory
				.getSocketFactory();
		sslSocketFactory
				.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		registry.register(new Scheme("https", sslSocketFactory, 443));
		ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(
				parameter, registry);
		client = new DefaultHttpClient(manager, parameter);

	}

	public static HttpManager getInstance() {
		if (instance == null) {
			instance = new HttpManager();
		}
		return instance;
	}

	public String loadAsString(String url) throws IOException {
		return loadAsString(loadAsStream(new HttpGet(url)));
	}

	public InputStream loadAsStream(String url) throws IOException {
		return loadAsStream(new HttpGet(url));
	}

	public JSONObject loadAsJSONObject(String url) throws IOException,
			JSONException {
		return new JSONObject(loadAsString(url));
	}

	public JSONArray loadAsJSONArray(String url) throws IOException,
			JSONException {
		return new JSONArray(loadAsString(url));
	}

	public Bitmap loadAsBitmap(String url) throws IOException {

		InputStream content = null;
		Bitmap bitmap = null;
		BitmapFactory.Options o = new BitmapFactory.Options();
		o.inJustDecodeBounds = false;
		try {
			content = loadAsStream(new HttpGet(url));
			bitmap = BitmapFactory.decodeStream(content, null, o);
		} finally {
			if (content != null) {
				try {
					content.close();
				} catch (IOException e) {
					throw e;
				}
			}
		}
		return bitmap;
	}

	private InputStream loadAsStream(HttpRequestBase request)
			throws IOException {
		InputStream content = null;
		// making a request
		HttpResponse response = client.execute(request);
		int statusCode = response.getStatusLine().getStatusCode();
		// if bad connection
		if (statusCode != HttpStatus.SC_OK) {
			String entityValue = null;
			entityValue = EntityUtils.toString(response.getEntity());
			throw new IOException(response.getStatusLine().getReasonPhrase()
					+ " " + entityValue + " " + statusCode);
		}

		content = response.getEntity().getContent();
		return content;
	}

	private String loadAsString(InputStream content) throws IOException {
		BufferedReader reader = null;
		try {

			reader = new BufferedReader(new InputStreamReader(content), 8192);

			StringBuilder sb = new StringBuilder();
			String line = null;
			try {
				while ((line = reader.readLine()) != null) {
					sb.append(line)
							.append(System.getProperty("line.separator"));
				}
			} catch (IOException e) {
				throw e;
			}
			String value = sb.toString();
			return value;
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					throw e;
				}
			}
			if (content != null) {
				try {
					content.close();
				} catch (IOException e) {
					throw e;
				}
			}
		}
	}
}
